package gui.parser;

import java.io.Reader;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import gui.Activity;
import gui.Application;
import gui.exception.ManifestNotFoundException;
import gui.framework.intent.IntentFilter;
import gui.parser.bean.Manifest;
import gui.parser.bean.UsesJdk;

/**
 * 清单文件解析器
 * 
 * @author chenj_000
 *
 */
public class ManifestParser {

	private Manifest manifest;
	private Activity temp_activity;
	private IntentFilter temp_intent_filter;

	public Manifest getManifest() {
		return manifest;
	}

	public Manifest parser(Reader reader) {
		try {
			XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
			parser.setInput(reader);
			int eventType = parser.getEventType();
			String tagName;
			while (eventType != XmlPullParser.END_DOCUMENT) {
				tagName = parser.getName();
				switch (eventType) {
				case XmlPullParser.START_TAG: {
					startTag(tagName, parser);
				}
					break;
				case XmlPullParser.END_TAG: {
					endTag(tagName, parser);
				}
					break;
				case XmlPullParser.TEXT: {
				}
					break;
				}
				eventType = parser.next();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ManifestNotFoundException(e);
		}
		return manifest;
	}

	private void endTag(String tagName, XmlPullParser parser) {
		switch (tagName) {
		case "activity": {
			temp_activity = null;
		}
			break;
		case "intent-filter": {
			temp_activity.setIntentFilter(temp_intent_filter);
			temp_intent_filter = null;
		}
			break;
		default:
			break;
		}
	}

	private void startTag(String tagName, XmlPullParser parser) {
		switch (tagName) {
		case "manifest": {
			manifest = new Manifest();
			int count = parser.getAttributeCount();
			for (int i = 0; i < count; i++) {
				switch (parser.getAttributeName(i)) {
				case "package": {
					manifest.setPackage_name(parser.getAttributeValue(i));
				}
					break;
				case "gui:versionCode": {
					manifest.setVersion_code(Integer.parseInt(parser.getAttributeValue(i)));
				}
					break;
				case "gui:versionName": {
					manifest.setVersion_name(parser.getAttributeValue(i));
				}
					break;
				default:
					break;
				}
			}
		}
			break;
		case "uses-jdk": {
			UsesJdk jdk = new UsesJdk();
			int count = parser.getAttributeCount();
			for (int i = 0; i < count; i++) {
				switch (parser.getAttributeName(i)) {
				case "gui:minVersion": {
					jdk.setMinVersion(parser.getAttributeValue(i));
				}
					break;
				case "gui:targetVersion": {
					jdk.setTargetVersion(parser.getAttributeValue(i));
				}
					break;
				default:
					break;
				}
			}
			manifest.setUses_jdk(jdk);
		}
			break;
		case "application": {
			Application application = null;
			String label = null;
			int count = parser.getAttributeCount();
			for (int i = 0; i < count; i++) {
				switch (parser.getAttributeName(i)) {
				case "gui:name": {
					String name = parser.getAttributeValue(i);
					try {
						if (name.startsWith("\\.")) {
							application = (Application) Class.forName(manifest.getPackage_name() + name).newInstance();
						} else {
							application = (Application) Class.forName(name).newInstance();
						}
					} catch (InstantiationException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
				}
					break;
				case "gui:label": {
					label = parser.getAttributeValue(i);
				}
					break;
				default:
					break;
				}
			}
			if (application == null)
				application = new Application();
			application.setLabel(label);
			manifest.setApplication(application);
		}
			break;
		case "activity": {
			String label = null;
			int count = parser.getAttributeCount();
			for (int i = 0; i < count; i++) {
				switch (parser.getAttributeName(i)) {
				case "gui:name": {
					String name = parser.getAttributeValue(i);
					try {
						if (name.charAt(0) == '.') {
							temp_activity = (Activity) Class.forName(manifest.getPackage_name() + name).newInstance();
						} else {
							temp_activity = (Activity) Class.forName(name).newInstance();
						}
					} catch (InstantiationException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
				}
					break;
				case "gui:label": {
					label = parser.getAttributeValue(i);
				}
					break;
				default:
					break;
				}
			}
			temp_activity.setLabel(label);
			manifest.addActivity(temp_activity);
		}
			break;
		case "intent-filter": {
			temp_intent_filter = new IntentFilter();
		}
			break;
		case "action": {
			int count = parser.getAttributeCount();
			for (int i = 0; i < count; i++) {
				switch (parser.getAttributeName(i)) {
				case "gui:name": {
					String name = parser.getAttributeValue(i);
					temp_intent_filter.addAction(name);
				}
					break;
				}
			}
		}
			break;
		case "category": {
			int count = parser.getAttributeCount();
			for (int i = 0; i < count; i++) {
				switch (parser.getAttributeName(i)) {
				case "gui:name": {
					String name = parser.getAttributeValue(i);
					temp_intent_filter.addCategory(name);
				}
					break;
				}
			}
		}
			break;
		default:
			break;
		}
	}
}
